/* Copyright (c) 2009 Nordic Semiconductor. All Rights Reserved.
 *
 * The information contained herein is confidential property of Nordic
 * Semiconductor ASA.Terms and conditions of usage are described in detail
 * in NORDIC SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
 *
 * Licensees are granted free, non-transferable use of the information. NO
 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
 * the file.
 *
 */

/** @file
* @brief SPI Master loopback example.
* @defgroup spi_master_example SPI master loopback usage example
* @{
* @ingroup nrf_examples_nrf6310
*
* @brief SPI master example.
*
* This example needs that the slave is configured to transmit the received bytes. That is the slave
* behaves as a loopback device for the master. The loopback can also be achieved without using a slave device at all by wiring MOSI and
* MISO pins of the spi master together. @ref TX_RX_MSG_LENGTH number of bytes are transmitted through the master and the received bytes are
* verified to be the same as transmitted. IF there is an error, gpio pin for relevant spi module is set high to show the error @sa ERROR_PIN_SPI0,
* @sa ERROR_PIN_SPI1. If there is error from both modules that is if both pins are set high, then this application loops for ever
*
*/

#include "spi_master.h"
#include "nrf_delay.h"
#include "common.h"
#include "spi_master_config.h"

static uint8_t tx_data[TX_RX_MSG_LENGTH]; /*!< SPI TX buffer */
static uint8_t rx_data[TX_RX_MSG_LENGTH]; /*!< SPI RX buffer */

#define DELAY_MS               100        /*!< Timer Delay in milli-seconds */

/** Tests SPI master.
 * @param lsb_first If true, least significant bits are transferred first
 * @param mod_num spi module to be used, either SPI0 or SPI1 from enumeration SPIModuleNumber
 * @retval true 
 * @retval false Error occurred
 */
static bool test_spi_tx_rx(SPIModuleNumber mod_num, uint8_t lsb_first)
{
  // Use SPI0, mode0 with lsb shifted as requested
  uint32_t *spi_base_address = spi_master_init(mod_num, SPI_MODE0, (bool)lsb_first);
  if (spi_base_address == 0)
    return false;

  // Fill tx_data with some simple pattern, rx is filled with zero's so that after receiving from
  // slave we verify rx_Data is same as tx_data
  for(uint8_t i = 0; i < TX_RX_MSG_LENGTH; i++)
  {
    tx_data[i] = i;
    rx_data[i] = 0;
  }

  // Transmit TX_RX_MSG_LENGTH bytes from tx_data and receive same number of bytes and data into rx_data
  if(!spi_master_tx_rx(spi_base_address, TX_RX_MSG_LENGTH, (const uint8_t *)tx_data, rx_data) )
    return false;

  // Validate that we got all transmitted bytes back in the exact order
  for(uint8_t i = 0; i < TX_RX_MSG_LENGTH; i++)
  {
    if( tx_data[i] != rx_data[i] )
      return false;
  }
  return true;
}

/**
 * main() function
 * @return 0. int return type required by ANSI/ISO standard. 
 */
int main(void)
{
  bool ret0, ret1;

  NRF_GPIO->DIRSET = (1UL << ERROR_PIN_SPI0);
  NRF_GPIO->DIRSET = (1UL << ERROR_PIN_SPI1);
  while(true)
  {
    // SPI0
    ret0 = test_spi_tx_rx(SPI0, 1 );   /*!< test with shift Lsb first mode 0 */
    if (ret0)
    {
      // previous tx/rx was successful with lsb shifted first, try the same with lsb shifted last
      nrf_delay_ms(DELAY_MS);   /*!< This delay is just fot the events ready signal to be visually clear if connted to LED if DEBUG flag is enabled in spi_master library */
      ret0 = test_spi_tx_rx(SPI0, 0 );
    }

    if (!ret0)
    {
      // Set gpio pin number ERROR_PIN to convey error, this pin can be connected to LED for visual debug
      NRF_GPIO->OUTSET = (1UL << ERROR_PIN_SPI0);
    }

    // SPI1
    ret1 = test_spi_tx_rx(SPI1, 1 );   /*!< test with shift Lsb first mode 0 */
    if (ret1)
    {
      // previous tx/rx was successful with lsb shifted first, try the same with lsb shifted last
      nrf_delay_ms(DELAY_MS);   /*!< This delay is just fot the events ready signal to be visually clear if connted to LED if DEBUG flag is enabled in spi_master library */
      ret1 = test_spi_tx_rx(SPI1, 0 );
    }

    if (!ret1)
    {
      // Set gpio pin number ERROR_PIN to convey error, this pin can be connected to LED for visual debug
      NRF_GPIO->OUTSET = (1UL << ERROR_PIN_SPI1);
    }

    if (!ret0 && !ret1 )
    {
      while(true)
      {
          // Loop forever
      }
    }
  }
}

/**
 *@}
 **/
